package com.drink.yan.svc.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.drink.yan.core.mapper.YanOrderItemMapper;
import com.drink.yan.core.mapper.YanOrderMapper;
import com.drink.yan.core.mapper.YanSkuMapper;
import com.drink.yan.domain.YanOrderDo;
import com.drink.yan.domain.YanUserDo;
import com.drink.yan.intf.define.*;
import com.drink.yan.intf.entity.*;
import com.drink.yan.intf.entity.io.YanJsonMapIo;
import com.drink.yan.intf.vo.OrderItemVo;
import com.drink.yan.intf.vo.OrderVo;
import com.drink.yan.intf.vo.SkuVo;
import com.drink.yan.intf.vo.UserVo;
import com.drink.yan.web.rest.req.cmd.ApplyOrderCmd;
import com.drink.yan.web.rest.req.cmd.OrderOperateCmd;
import com.drink.yan.web.rest.req.qry.PageMyDataQry;
import com.drink.yan.web.rest.req.qry.PageOrderQry;
import com.github.meixuesong.aggregatepersistence.Aggregate;
import com.github.meixuesong.aggregatepersistence.AggregateFactory;
import com.github.meixuesong.aggregatepersistence.ChangedEntity;
import com.github.meixuesong.aggregatepersistence.DataObjectUtils;
import com.meta.framework.act.entity.SysUser;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * java类简单作用描述
 *
 * @Title:
 * @Package: com.drink.yan.svc.service.
 * @Author: M.simple
 * @Remark: The modified content
 * @CreateDate: 2023/11/24 20:44
 * @Version: v2.0
 */
@Service
public class YanOrderService extends ServiceImpl<YanOrderMapper, YanOrder> {

	@Resource
	private YanSkuMapper yanSkuMapper;

	@Resource
	private YanOrderItemMapper yanOrderItemMapper;

	@Resource
	private YanSkuService yanSkuService;

	@Resource
	private YanUserService yanUserService;

	@Resource
	private YanCommissionService yanCommissionService;


	public List<SkuVo> listCourse(PageMyDataQry qry) {

		List<SkuVo> skuVos = this.baseMapper.listCourse(qry);

		skuVos.forEach(x->{
			x.setSkuImgs(JSONObject.parseArray(x.getSkuImgsStr(), String.class));
			x.setSkuLabels(JSONObject.parseArray(x.getSkuLabelsStr(), String.class));
			x.setSkuFiles(JSONObject.parseArray(x.getSkuFilesStr(), YanJsonMapIo.class));
		});

		return skuVos;
	}

	public List<SkuVo> listStudyFile(PageMyDataQry qry) {

		List<SkuVo> skuVos = this.baseMapper.listStudyFile(qry);

		skuVos.forEach(x->{
			x.setSkuImgs(JSONObject.parseArray(x.getSkuImgsStr(), String.class));
			x.setSkuLabels(JSONObject.parseArray(x.getSkuLabelsStr(), String.class));
			x.setSkuFiles(JSONObject.parseArray(x.getSkuFilesStr(), YanJsonMapIo.class));
		});

		return skuVos;
	}

	public Aggregate<YanOrderDo> getYanUserDo(Long orderNo) {

		Aggregate<YanOrderDo> aggregate = AggregateFactory.createAggregate(new YanOrderDo());


		YanOrder yanOrder = this.baseMapper.selectById(orderNo);
		YanOrderDo yanOrderDo = yanOrder.transform(YanOrderDo.class);
		CompletableFuture<List<YanOrderItem>> yanOrderItemCompletable = listOrderItem(orderNo);

		try {
			yanOrderDo.setYanOrderItems(yanOrderItemCompletable.get());
			aggregate = AggregateFactory.createAggregate(yanOrderDo);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return aggregate;
	}

	private CompletableFuture<List<YanOrderItem>> listOrderItem(Long orderNo) {


		return CompletableFuture.supplyAsync(() -> {
			LambdaQueryWrapper<YanOrderItem> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(YanOrderItem::getOrderNo, orderNo);
			return yanOrderItemMapper.selectList(queryWrapper);
		});
	}

	public YanOrder applyOrder(ApplyOrderCmd cmd) {

		List<Long> skuIds = cmd.getSkuIds();

		List<Long> skuIds1 = cmd.getSkuIds();
		List<YanSku> yanSkus = listSku(skuIds1);
		Aggregate<YanUserDo> yanUserDo = yanUserService.getYanUserDo(cmd.getCustomerUid());

		Aggregate<YanOrderDo> yanOrderDo = YanOrderDo.createOrder(cmd, yanSkus, yanUserDo.getRoot());

		this.saveOrder(yanOrderDo);

		//增加改商品的下单次数
		YanOrderDo root = yanOrderDo.getRoot();
		List<YanOrderItem> yanOrderItems = root.getYanOrderItems();
		yanOrderItems.forEach(x -> {
			YanSku skuDetail = yanSkuService.getSkuDetail(x.getSkuId());
			skuDetail.setOrderCount(skuDetail.getOrderCount() + 1);
			yanSkuService.saveSku(skuDetail);
		});

		return root;
	}

	private Aggregate<YanOrderDo> saveOrder(Aggregate<YanOrderDo> aggregate) {

		if (Objects.isNull(aggregate.getRoot().getOrderNo())) {
			YanOrderDo root = aggregate.getRoot();
			YanOrder order = root.transform(YanOrder.class);
			this.baseMapper.insert(order);
			aggregate.getRoot().setOrderNo(order.getOrderNo());

			root.getYanOrderItems().forEach(x -> {
				x.setOrderNo(aggregate.getRoot().getOrderNo());
				this.yanOrderItemMapper.insert(x);
			});

		} else if (aggregate.isChanged()) {
			YanOrderDo root = aggregate.getRoot();
			updateYanOrder(aggregate);

			updateOrderItems(aggregate);

			insertOrderItems(aggregate);
		}

		return aggregate;

	}

	private void updateOrderItems(Aggregate<YanOrderDo> orderAggregate) {
		Collection<ChangedEntity<YanOrderItem>> entityPairs = orderAggregate.findChangedEntitiesWithOldValues(YanOrderDo::getYanOrderItems, YanOrderItem::getId);
		for (ChangedEntity<YanOrderItem> pair : entityPairs) {
			Set<String> changedFields = DataObjectUtils.getChangedFields(pair.getOldEntity(), pair.getNewEntity());
			if (!CollectionUtils.isEmpty(changedFields)) {
				this.yanOrderItemMapper.updateById(pair.getNewEntity());
			}
		}
	}

	private void insertOrderItems(Aggregate<YanOrderDo> orderAggregate) {
		Collection<YanOrderItem> newEntities = orderAggregate.findNewEntities(YanOrderDo::getYanOrderItems, (item) -> item.getId() == null);
		if (newEntities.size() > 0) {
			newEntities.forEach(x -> {
				x.setOrderNo(orderAggregate.getRoot().getOrderNo());
				yanOrderItemMapper.insert(x);
			});
		}
	}

	private void updateYanOrder(Aggregate<YanOrderDo> aggregate) {

		YanOrder order = aggregate.getRoot().transform(YanOrder.class);
		Set<String> changedFields = DataObjectUtils.getChangedFields(aggregate.getRootSnapshot(), aggregate.getRoot());
		if (!CollectionUtils.isEmpty(changedFields)) {
			this.baseMapper.updateById(order);
		}
	}

	private List<YanSku> listSku(List<Long> skuIds) {

		LambdaQueryWrapper<YanSku> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(YanSku::getSkuId, skuIds);
		List<YanSku> yanSkus = yanSkuMapper.selectList(queryWrapper);

		return yanSkus;
	}

	public YanOrder payOrder(OrderOperateCmd cmd) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(cmd.getOrderNo());
		yanUserDo.getRoot().payOrder(cmd);

		Aggregate<YanOrderDo> order = saveOrder(yanUserDo);

		return order.getRoot();
	}

	public YanOrder deliverOrder(OrderOperateCmd cmd) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(cmd.getOrderNo());
		yanUserDo.getRoot().deliverOrder(cmd);

		Aggregate<YanOrderDo> order = saveOrder(yanUserDo);

		return order.getRoot();
	}

	public YanOrder receiveOrder(OrderOperateCmd cmd) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(cmd.getOrderNo());
		yanUserDo.getRoot().receiveOrder(cmd);

		Aggregate<YanOrderDo> order = saveOrder(yanUserDo);

		return order.getRoot();
	}

	public YanOrder completeOrder(OrderOperateCmd cmd) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(cmd.getOrderNo());
		yanUserDo.getRoot().completeOrder(cmd);

		Aggregate<YanOrderDo> order = saveOrder(yanUserDo);

		//发放购买学姐资料的佣金
		List<YanOrderItem> yanOrderItems = order.getRoot().getYanOrderItems();
		yanOrderItems.forEach(x -> {
			YanSku skuDetail = yanSkuService.getSkuDetail(x.getSkuId());
			if (YanSkuOriginalE.senior.getCode().equals(skuDetail.getSkuOriginal())) {
				YanCommission yanCommission = new YanCommission();
				//yanCommission.setStudentId(cmd.getUserId());
				yanCommission.setUserId(skuDetail.getBelongUid());
				yanCommission.setCommissionType(YanCommissionTypeE.buy_ebook.getCode());
				yanCommission.setCommissionStatus(YanCommissionStatusE.in_account.getCode());
				yanCommission.setCommissionTypeName(YanCommissionTypeE.buy_ebook.getRemark());
				yanCommission.setCommissionName(skuDetail.getSkuName());
				yanCommission.setBusinessAmount(skuDetail.getSkuPrice());
				yanCommission.setBusinessKey(order.getRoot().getOrderNo());
				yanCommission.setBusinessSubKey(x.getSkuId());
				yanCommission.setUserType(YanUserTypeE.senior.getCode());
				yanCommissionService.generateCommission(yanCommission);
			}else if (YanSkuE.course.getCode().equals(skuDetail.getSkuType())) {
				//给辅导员的佣金
				YanCommission yanCommission = new YanCommission();
				//yanCommission.setStudentId(cmd.getUserId());
				UserVo userVo = yanUserService.getYanUserVo(order.getRoot().getCustomerUid());
				yanCommission.setUserId(userVo.getYanUserStudent().getCounselorUserId());
				yanCommission.setAgencyUserId(userVo.getYanUserStudent().getAgencyUserId());
				yanCommission.setStudentId(userVo.getUserId());
				yanCommission.setCommissionType(YanCommissionTypeE.course.getCode());
				yanCommission.setCommissionStatus(YanCommissionStatusE.in_account.getCode());
				yanCommission.setCommissionTypeName(YanCommissionTypeE.course.getRemark());
				yanCommission.setCommissionName(skuDetail.getSkuName());
				yanCommission.setBusinessAmount(skuDetail.getSkuPrice());
				yanCommission.setBusinessKey(order.getRoot().getOrderNo());
				yanCommission.setBusinessSubKey(x.getSkuId());
				yanCommission.setUserType(YanUserTypeE.counselor.getCode());
				yanCommissionService.generateCommission(yanCommission);

				//给代理的佣金
				YanCommission agencyCommission = new YanCommission();
				//yanCommission.setStudentId(cmd.getUserId());
				agencyCommission.setUserId(userVo.getYanUserStudent().getAgencyUserId());
				agencyCommission.setStudentId(userVo.getUserId());
				agencyCommission.setCommissionType(YanCommissionTypeE.course.getCode());
				agencyCommission.setCommissionStatus(YanCommissionStatusE.in_account.getCode());
				agencyCommission.setCommissionTypeName(YanCommissionTypeE.course.getRemark());
				agencyCommission.setCommissionName(skuDetail.getSkuName());
				agencyCommission.setBusinessAmount(skuDetail.getSkuPrice());
				agencyCommission.setBusinessKey(order.getRoot().getOrderNo());
				agencyCommission.setBusinessSubKey(x.getSkuId());
				agencyCommission.setUserType(YanUserTypeE.agency.getCode());
				yanCommissionService.generateCommission(agencyCommission);
			}
		});

		return order.getRoot();
	}

	public YanOrder cancelOrder(OrderOperateCmd cmd) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(cmd.getOrderNo());
		yanUserDo.getRoot().cancelOrder(cmd);

		Aggregate<YanOrderDo> order = saveOrder(yanUserDo);

		return order.getRoot();
	}

	public List<OrderVo> listOrder(PageOrderQry qry) {

		return this.baseMapper.listOrder(qry);
	}

	public OrderVo getOrderDetail(Long orderNo) {
		Aggregate<YanOrderDo> yanUserDo = getYanUserDo(orderNo);

		YanOrderDo root = yanUserDo.getRoot();
		OrderVo orderVo = root.transform(OrderVo.class);
		if(Objects.nonNull(root.getCreateBy())){
			Aggregate<YanUserDo> userDo = yanUserService.getYanUserDo(root.getCreateBy());
			Optional.ofNullable(userDo.getRoot().getNickName()).ifPresent(orderVo::setCreateByName);
		}

		List<OrderItemVo> yanOrderItems = orderVo.getYanOrderItems();
		if(CollectionUtils.isEmpty(yanOrderItems)){
			return orderVo;
		}

		List<Long> skuIdList = yanOrderItems.stream().map(OrderItemVo::getSkuId).collect(Collectors.toList());
		List<YanSku> yanSkus = listSku(skuIdList);
		Map<Long, YanSku> yanSkuMap = yanSkus.stream().collect(Collectors.groupingBy(YanSku::getSkuId, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));
		List<OrderItemVo> orderItemVos = yanOrderItems.stream().map(x -> {
			OrderItemVo orderItemVo = x.transform(OrderItemVo.class);
			YanSku yanSku = yanSkuMap.get(x.getSkuId());
			orderItemVo.setYanSku(yanSku);
			return orderItemVo;
		}).collect(Collectors.toList());
		orderVo.setYanOrderItems(orderItemVos);
		return orderVo;
	}
}
